<template>
  <view class="editor-container">
    <!-- 顶部导航栏 -->
    <u-navbar :title="isCustom ? '编辑产品特色自定义' : '编辑产品特色'" autoBack leftIcon="arrow-left" fixed safeAreaInsetTop />

    <!-- 工具栏 -->
    <view class="toolbar">
      <view class="toolbar-group">
        <view class="toolbar-btn" :class="{ active: formatState.bold }" @click="format('bold')">
          <text class="btn-icon bold">B</text>
        </view>
        <view class="toolbar-btn" :class="{ active: formatState.italic }" @click="format('italic')">
          <text class="btn-icon italic">I</text>
        </view>
        <view class="toolbar-btn" :class="{ active: formatState.underline }" @click="format('underline')">
          <text class="btn-icon underline">U</text>
        </view>
      </view>
      <view class="toolbar-group">
        <view class="toolbar-btn" :class="{ active: formatState.list === 'ordered' }" @click="format('insertOrderedList')">
          <text class="btn-text">1.</text>
        </view>
        <view class="toolbar-btn" :class="{ active: formatState.list === 'bullet' }" @click="format('insertUnorderedList')">
          <text class="btn-text">•</text>
        </view>
      </view>
      <view class="toolbar-group">
        <view class="toolbar-btn" @click="format('header', 'H1')">
          <text class="btn-text">H1</text>
        </view>
        <view class="toolbar-btn" @click="format('header', 'H2')">
          <text class="btn-text">H2</text>
        </view>
      </view>
      <view class="toolbar-group">
        <view class="toolbar-btn" :class="{ active: formatState.align === 'left' }" @click="format('align', 'left')">
          <text class="btn-text">←</text>
        </view>
        <view class="toolbar-btn" :class="{ active: formatState.align === 'center' }" @click="format('align', 'center')">
          <text class="btn-text">↔</text>
        </view>
        <view class="toolbar-btn" :class="{ active: formatState.align === 'right' }" @click="format('align', 'right')">
          <text class="btn-text">→</text>
        </view>
      </view>
      <view class="toolbar-group">
        <view class="toolbar-btn" @click="insertImage">
          <text class="btn-text">🖼️</text>
        </view>
        <view class="toolbar-btn" @click="format('removeFormat')">
          <text class="btn-text">✕</text>
        </view>
      </view>
    </view>

    <!-- 富文本编辑器 -->
    <view class="editor-wrapper">
      <editor
        id="editor"
        class="ql-container"
        placeholder="请输入产品特色内容..."
        :show-img-size="true"
        :show-img-toolbar="true"
        :show-img-resize="true"
        @ready="onEditorReady"
        @statuschange="onStatusChange"
      />
    </view>

    <!-- 上传进度提示 -->
    <view class="upload-progress-container" v-if="hasUploadingImages">
      <view class="upload-progress-item" v-for="(item, index) in uploadingImages" :key="item.id">
        <view class="upload-progress-header">
          <text class="upload-progress-text">图片上传中 ({{ index + 1 }}/{{ uploadingImages.length }})</text>
          <text class="upload-progress-percent">{{ item.progress || 0 }}%</text>
        </view>
        <view class="upload-progress-bar">
          <view class="upload-progress-fill" :style="{ width: (item.progress || 0) + '%' }"></view>
        </view>
        <view class="upload-progress-status" v-if="item.status === 'failed'">
          <text class="upload-status-text failed">上传失败，请重试</text>
        </view>
        <view class="upload-progress-status" v-else-if="item.status === 'success'">
          <text class="upload-status-text success">上传成功</text>
        </view>
      </view>
    </view>

    <!-- 底部按钮 -->
    <view class="bottom-bar">
      <button class="btn-cancel" @click="goBack">取消</button>
      <button class="btn-save" @click="saveFeatures" :disabled="isSaving || hasUploadingImages">
        {{ isSaving ? '保存中...' : hasUploadingImages ? '图片上传中...' : '保存并返回' }}
      </button>
    </view>

    <canvas canvas-id="featureEditorTempCanvas" id="featureEditorTempCanvas"
      :style="`width: ${canvasWidth}px; height: ${canvasHeight}px; position: absolute; left: -9999px; top: -9999px;`"></canvas>
  </view>
</template>

<script>
import { useProductStore } from '@/store/product.js';

export default {
  data() {
    return {
      productStore: null,
      features: [],
      editorCtx: null,
      isSaving: false,
      isUploading: false,
      isCustom: false, // 是否为自定义模式
      // 正在上传的图片列表（追踪所有上传任务）
      uploadingImages: [],
      // 图片路径映射表（本地路径 -> 服务器URL）
      imagePathMap: {},
      // 图片尺寸缓存
      imageDimensionCache: {},
      canvasWidth: 800,
      canvasHeight: 800,
      // 编辑器格式状态
      formatState: {
        bold: false,
        italic: false,
        underline: false,
        align: '',
        list: ''
      }
    };
  },

  onLoad(options) {
    this.productStore = useProductStore();
    this.isCustom = options.isCustom === 'true';
    this.loadFeatures();

    // 延迟加载内容到编辑器，确保编辑器已准备好
    this.$nextTick(() => {
      this.loadContentToEditor();
    });
  },

  computed: {
    // 检查是否有正在上传的图片
    hasUploadingImages() {
      return this.uploadingImages.length > 0;
    }
  },

  methods: {
    // 编辑器就绪
    onEditorReady() {
      uni.createSelectorQuery()
        .in(this)
        .select('#editor')
        .context((res) => {
          this.editorCtx = res.context;
          console.log('编辑器已准备就绪:', this.editorCtx);
        })
        .exec();
    },

    // 编辑器状态变化
    onStatusChange(e) {
      const detail = e.detail;
      console.log('编辑器状态变化:', detail);

      // 更新格式状态
      this.formatState.bold = detail.bold || false;
      this.formatState.italic = detail.italic || false;
      this.formatState.underline = detail.underline || false;
      this.formatState.align = detail.align || '';
      this.formatState.list = detail.list || '';
    },

    // 加载已有的产品特色数据
    loadFeatures() {
      console.log('=== 加载产品特色数据 ===', this.isCustom ? '(自定义模式)' : '');

      const dataKey = this.isCustom ? 'productFeaturesCustom' : 'productFeatures';
      const htmlKey = this.isCustom ? 'productFeaturesCustomHtml' : 'productFeaturesHtml';

      // 优先从productFeatures加载（用于数据结构）
      if (this.productStore?.subPageData?.[dataKey]) {
        this.features = JSON.parse(JSON.stringify(this.productStore.subPageData[dataKey]));
        console.log(`从${dataKey}加载数据:`, this.features);
      } else {
        this.features = [];
        console.log(`${dataKey}为空`);
      }

      // 记录是否有HTML内容
      if (this.productStore?.subPageData?.[htmlKey]) {
        console.log(`存在${htmlKey}，长度:`, this.productStore.subPageData[htmlKey].length);
      } else {
        console.log(`${htmlKey}为空`);
      }
    },

    // 将已保存的内容加载到编辑器中
    loadContentToEditor() {
      if (!this.editorCtx) {
        console.log('编辑器还未准备好');
        // 如果编辑器还没准备好，延迟再试
        setTimeout(() => {
          this.loadContentToEditor();
        }, 200);
        return;
      }

      console.log('=== 开始加载内容到编辑器 ===');

      const htmlKey = this.isCustom ? 'productFeaturesCustomHtml' : 'productFeaturesHtml';
      // 优先从productFeaturesHtml加载（完整HTML内容）
      if (this.productStore?.subPageData?.[htmlKey]) {
        const htmlContent = this.productStore.subPageData[htmlKey];
        console.log(`从${htmlKey}加载HTML内容`);
        console.log('HTML内容长度:', htmlContent.length);
        console.log('HTML内容预览:', htmlContent.substring(0, 200));

        this.editorCtx.setContents({
          html: htmlContent,
          success: () => {
            console.log('✅ HTML内容加载成功');
            this.applyNormalizedImageStyles();
          },
          fail: (err) => {
            console.error('❌ HTML内容加载失败:', err);
          }
        });
      }
      // 降级方案：从productFeatures构建HTML
      else if (this.features && this.features.length > 0) {
        console.log('productFeaturesHtml为空，从productFeatures构建HTML');
        console.log('features数据:', this.features);

        // 按照order排序
        const sortedFeatures = [...this.features].sort((a, b) => (a.order || 0) - (b.order || 0));
        console.log('排序后的features:', sortedFeatures);

        // 构建完整的HTML内容
        let htmlContent = '';

        sortedFeatures.forEach((item, index) => {
          console.log(`处理项目 ${index + 1}:`, item);

          if (item.type === 'text' && item.alt) {
            // 文本内容：转换为段落
            const paragraphs = item.alt.split('\n').filter(p => p.trim());
            paragraphs.forEach(paragraph => {
              htmlContent += `<p>${paragraph}</p>`;
            });
            console.log('添加文本段落');
          } else if (item.type === 'image' && item.imgUrl) {
            // 图片内容：添加img标签
            htmlContent += `<p><img src="${item.imgUrl}" style="max-width: 100%;" alt="${item.alt || '产品特色图片'}"/></p>`;
            console.log('添加图片:', item.imgUrl);
          }
        });

        console.log('构建的完整HTML:', htmlContent);

        if (htmlContent) {
          // 将完整内容加载到编辑器
          this.editorCtx.setContents({
            html: htmlContent,
            success: () => {
              console.log('✅ 内容加载成功（从productFeatures构建）');
              this.applyNormalizedImageStyles();
            },
            fail: (err) => {
              console.error('❌ 内容加载失败:', err);
              // 如果setContents失败，尝试只加载文本
              const textFeature = sortedFeatures.find(item => item.type === 'text' && item.alt);
              if (textFeature) {
                this.editorCtx.insertText({
                  text: textFeature.alt
                });
                console.log('降级方案：只加载了文本内容');
              }
            }
          });
        } else {
          console.log('⚠️ 没有可加载的内容');
        }
      } else {
        console.log('⚠️ 没有任何内容需要加载（productFeaturesHtml和productFeatures都为空）');
      }

      console.log('=== 加载内容完成 ===\n');
    },

    // 格式化文本
    format(name, value) {
      if (!this.editorCtx) {
        uni.showToast({ title: '编辑器未准备好', icon: 'none' });
        return;
      }
      this.editorCtx.format(name, value);
    },

    // 插入图片
    insertImage() {
      if (!this.editorCtx) {
        uni.showToast({ title: '编辑器未准备好，请稍候', icon: 'none' });
        return;
      }

      this.chooseImage();
    },

    // 选择图片
    async chooseImage() {
      if (this.isUploading) return;

      let tempFilePath = '';

      try {
        const res = await new Promise((resolve, reject) => {
          uni.chooseImage({
            count: 1,
            sizeType: ['compressed', 'original'],
            success: resolve,
            fail: reject
          });
        });

        const tempFile = res.tempFiles[0];
        tempFilePath = tempFile.path || res.tempFilePaths[0]; // 本地临时路径
        const maxSize = 5 * 1024 * 1024; // 5MB

        if (tempFile.size > maxSize) {
          uni.showToast({ title: '图片大小不能超过5MB', icon: 'none' });
          return;
        }

        const imageInfo = await uni.getImageInfo({ src: tempFilePath });
        if (imageInfo.width < 600 || imageInfo.height < 600) {
          uni.showToast({ title: '图片像素需至少600×600，请重新选择', icon: 'none' });
          return;
        }

        const { path: processedPath, width: finalWidth, height: finalHeight } = await this.convertToJpegWithMaxWidth(tempFilePath, imageInfo);
        tempFilePath = processedPath;
        this.imageDimensionCache[tempFilePath] = {
          width: finalWidth,
          height: finalHeight
        };

        this.isUploading = true;
        
        // 添加到正在上传列表
        const uploadId = Date.now() + '_' + Math.random();
        this.uploadingImages.push({
          id: uploadId,
          path: tempFilePath,
          status: 'uploading', // uploading, success, failed
          progress: 0 // 上传进度 0-100
        });

        // ===== 【显示上传中提示】 =====
        uni.showLoading({
          title: '上传图片中...',
          mask: true
        });

        console.log('🖼️ [富文本编辑器] ========== 开始插入图片 ==========');
        console.log('🖼️ [富文本编辑器] 选择的图片本地路径:', tempFilePath);
        console.log('🖼️ [富文本编辑器] 图片大小:', tempFile.size, 'bytes');
        console.log('🖼️ [富文本编辑器] 当前上传任务数:', this.uploadingImages.length);

        // ===== 【优化1】立即插入本地图片，不等待上传 =====
        console.log('🖼️ [富文本编辑器] 立即插入本地图片');

        if (this.editorCtx && tempFilePath) {
          try {
            // 【关键】使用insertImage而不是setContents，确保不会清除已有内容
            await new Promise((resolve, reject) => {
              this.editorCtx.insertImage({
                src: tempFilePath, // 先使用本地路径，立即显示
                alt: '产品特色图片',
                success: () => {
                  console.log('✅ [富文本编辑器] 本地图片插入成功（立即显示）');
                  resolve(true);
                },
                fail: (err) => {
                  console.error('❌ [富文本编辑器] 本地图片插入失败:', err);
                  reject(err);
                }
              });
            });

            await this.applyNormalizedImageStyles();

            // ===== 【图片显示后立即隐藏加载提示】 =====
            uni.hideLoading();

            // 提示用户图片已插入
            uni.showToast({ title: '图片已插入，正在上传...', icon: 'none', duration: 1500 });

          } catch (insertErr) {
            console.error('❌ [富文本编辑器] 插入本地图片失败:', insertErr);

            // ===== 【插入失败也要隐藏加载提示】 =====
            uni.hideLoading();

            // 如果insertImage失败，尝试手动插入
            await this.manualInsertImage(tempFilePath, true); // true表示是本地路径
          }
        }

        // ===== 【优化2】后台上传，不阻塞UI =====
        console.log('📤 [富文本编辑器] 后台上传图片到服务器');

        // 异步上传，不阻塞用户继续编辑
        this.uploadAndReplaceImage(tempFilePath, uploadId);

        console.log('🖼️ [富文本编辑器] ========== 图片已插入，后台上传中 ==========');

      } catch (err) {
        console.error('❌ [富文本编辑器] 操作失败:', err);
        console.error('❌ [富文本编辑器] 错误详情:', JSON.stringify(err));

        // ===== 【出错时也要隐藏加载提示】 =====
        uni.hideLoading();
        
        // 从上传列表中移除（标记为失败）
        const failedIndex = this.uploadingImages.findIndex(img => img.path === tempFilePath);
        if (failedIndex !== -1) {
          this.uploadingImages[failedIndex].status = 'failed';
          setTimeout(() => {
            this.uploadingImages.splice(failedIndex, 1);
          }, 2000);
        }

        if (err.errMsg && !err.errMsg.includes('cancel')) {
          uni.showToast({
            title: err.message || '图片上传失败，请重试',
            icon: 'none',
            duration: 2000
          });
        }
      } finally {
        this.isUploading = false;
      }
    },

    // 后台上传图片并替换URL（不阻塞用户操作）
    async uploadAndReplaceImage(tempFilePath, uploadId) {
      try {
        console.log('📤 [富文本编辑器] 开始后台上传');
        
        // 更新上传状态提示
        this.updateUploadStatus(uploadId, 'uploading');

        let uploadRes = null;
        let uploadSuccess = false;

        // 【添加重试机制】尝试3次上传
        for (let retry = 0; retry < 3; retry++) {
          try {
            console.log(`📤 [富文本编辑器] 第 ${retry + 1} 次尝试上传`);
            // 重置进度（如果是重试）
            if (retry > 0) {
              this.updateUploadProgress(uploadId, 0);
            }
            uploadRes = await this.uploadImageToServer(tempFilePath, uploadId);
            uploadSuccess = true;
            console.log('✅ [富文本编辑器] 后台上传成功:', uploadRes.url);
            break;
          } catch (uploadErr) {
            console.error(`❌ [富文本编辑器] 第 ${retry + 1} 次上传失败:`, uploadErr.message);
            if (retry < 2) {
              console.log('⏳ [富文本编辑器] 等待2秒后重试...');
              // 重试时重置进度
              this.updateUploadProgress(uploadId, 0);
              await new Promise(resolve => setTimeout(resolve, 2000));
            }
          }
        }

        if (!uploadSuccess || !uploadRes || !uploadRes.url) {
          console.error('❌ [富文本编辑器] 后台上传最终失败');
          
          // 更新上传状态为失败
          this.updateUploadStatus(uploadId, 'failed');
          
          // 显示失败提示
          uni.showToast({
            title: '图片上传失败，请重试',
            icon: 'none',
            duration: 2000
          });
          
          // 从上传列表中移除（延迟移除，让用户看到提示）
          setTimeout(() => {
            const index = this.uploadingImages.findIndex(img => img.id === uploadId);
            if (index !== -1) {
              this.uploadingImages.splice(index, 1);
            }
          }, 2000);
          
          return;
        }
        
        // 更新上传状态为成功
        this.updateUploadStatus(uploadId, 'success');
        
        // 显示成功提示
        uni.showToast({
          title: '图片上传成功',
          icon: 'none',
          duration: 1500
        });
        
        // 从上传列表中移除
        setTimeout(() => {
          const index = this.uploadingImages.findIndex(img => img.id === uploadId);
          if (index !== -1) {
            this.uploadingImages.splice(index, 1);
          }
        }, 1500);

        // 保存映射关系
        this.imagePathMap[tempFilePath] = uploadRes.url;
        console.log('📝 [富文本编辑器] 保存路径映射:', tempFilePath, '->', uploadRes.url);
        if (this.imageDimensionCache[tempFilePath]) {
          this.imageDimensionCache[uploadRes.url] = { ...this.imageDimensionCache[tempFilePath] };
        }
 
        // ===== 【关键】替换HTML中的本地路径为服务器URL =====
        console.log('🔄 [富文本编辑器] 开始替换本地路径为服务器URL');

        const currentHtml = await this.getEditorContent();
        console.log('📝 [富文本编辑器] 当前HTML长度:', currentHtml.length);

        // 处理路径中的特殊字符
        const escapedPath = tempFilePath
          .replace(/\\/g, '\\\\')
          .replace(/\//g, '\\/')
          .replace(/\?/g, '\\?')
          .replace(/\(/g, '\\(')
          .replace(/\)/g, '\\)');

        const regex = new RegExp(escapedPath, 'g');
        const newHtml = currentHtml.replace(regex, uploadRes.url);

        if (newHtml !== currentHtml) {
          console.log('🔄 [富文本编辑器] 检测到路径需要替换');

          // 【关键】使用setContents而不是insertImage来替换整个内容
          this.editorCtx.setContents({
            html: newHtml,
            success: () => {
              console.log('✅ [富文本编辑器] 路径替换成功，已更新为服务器URL');
              this.applyNormalizedImageStyles();
            },
            fail: (err) => {
              console.error('❌ [富文本编辑器] 路径替换失败:', err);
            }
          });
        } else {
          console.log('⚠️ [富文本编辑器] HTML中未找到本地路径，可能已经被替换或插入失败');
          this.applyNormalizedImageStyles();
        }

      } catch (err) {
        console.error('❌ [富文本编辑器] 后台上传流程失败:', err);
        
        // 更新上传状态为失败
        this.updateUploadStatus(uploadId, 'failed');
        
        // 显示失败提示
        uni.showToast({
          title: '图片上传失败，请重试',
          icon: 'none',
          duration: 2000
        });
        
        // 从上传列表中移除
        setTimeout(() => {
          const index = this.uploadingImages.findIndex(img => img.id === uploadId);
          if (index !== -1) {
            this.uploadingImages.splice(index, 1);
          }
        }, 2000);
      }
    },
    
    // 更新上传状态
    updateUploadStatus(uploadId, status) {
      const index = this.uploadingImages.findIndex(img => img.id === uploadId);
      if (index !== -1) {
        this.uploadingImages[index].status = status;
      }
    },
    
    // 检查HTML中是否有本地临时路径（未上传完成的图片）
    hasLocalImagePaths(html) {
      if (!html) return false;
      // 检查是否包含临时文件路径特征（如：http://tmp/ 或 file://）
      const localPathPatterns = [
        /http:\/\/tmp\//i,
        /file:\/\//i,
        /wxfile:\/\//i,
        /\.jpg|\.jpeg|\.png|\.gif/i  // 如果路径包含本地路径特征
      ];
      
      // 提取所有图片src
      const imgRegex = /<img[^>]+src=["']([^"']+)["'][^>]*>/gi;
      let match;
      
      while ((match = imgRegex.exec(html)) !== null) {
        const src = match[1];
        // 检查是否是本地路径（不是http或https开头的完整URL）
        if (!src.startsWith('http://') && !src.startsWith('https://')) {
          // 检查是否包含临时路径特征
          if (localPathPatterns.some(pattern => pattern.test(src))) {
            return true;
          }
          // 如果路径不包含域名，可能是本地路径
          if (!src.includes('://')) {
            return true;
          }
        }
      }
      
      return false;
    },

    // 手动插入图片到编辑器（降级方案）
    async manualInsertImage(imageUrl) {
      try {
        console.log('🔧 [富文本编辑器] 手动插入图片HTML:', imageUrl);

        const currentHtml = await this.getEditorContent();
        const imgHtml = `<p><img src="${imageUrl}" alt="产品特色图片"/></p>`;
        const newHtml = currentHtml + imgHtml;

        this.editorCtx.setContents({
          html: newHtml,
          success: () => {
            console.log('✅ [富文本编辑器] 手动插入成功');
            uni.showToast({ title: '图片已插入', icon: 'none', duration: 1500 });
            this.applyNormalizedImageStyles();
          },
          fail: (err) => {
            console.error('❌ [富文本编辑器] 手动插入失败:', err);
            uni.showToast({ title: '图片插入失败，请重试', icon: 'none' });
          }
        });
      } catch (err) {
        console.error('❌ [富文本编辑器] 手动插入异常:', err);
        uni.showToast({ title: '图片插入失败，请重试', icon: 'none' });
      }
    },

    // 上传图片到服务器
    uploadImageToServer(filePath, uploadId) {
      return new Promise((resolve, reject) => {
        console.log('📤 [富文本编辑器] 开始上传图片:', filePath);

        const token = uni.getStorageSync('accessToken') || '';
        console.log('📤 [富文本编辑器] Token存在:', !!token);

        if (!token) {
          console.error('❌ [富文本编辑器] Token不存在，无法上传');
          reject(new Error('未登录，请先登录'));
          return;
        }

        const uploadTask = uni.uploadFile({
          url: `https://abc.qctrips.cn/local-file/upload`,
          filePath: filePath,
          name: 'file',
          timeout: 60000, // 60秒超时
          header: {
            'Authorization': token
          },
          success: (uploadRes) => {
            console.log('📤 [富文本编辑器] 上传响应状态码:', uploadRes.statusCode);
            console.log('📤 [富文本编辑器] 上传响应数据:', uploadRes.data);

            if (uploadRes.statusCode === 200) {
              try {
                const data = JSON.parse(uploadRes.data);
                console.log('📤 [富文本编辑器] 解析后的数据:', data);

                if (data.code === 200 && data.data) {
                  const imageUrl = data.data.url || data.data.objectUrl;
                  console.log('✅ [富文本编辑器] 图片上传成功:', imageUrl);
                  
                  // 更新进度为100%
                  this.updateUploadProgress(uploadId, 100);
                  
                  resolve({
                    url: imageUrl,
                    width: data.data.width || 0,
                    height: data.data.height || 0
                  });
                } else {
                  console.error('❌ [富文本编辑器] 服务器返回错误:', data.msg || data.message);
                  reject(new Error(data.msg || data.message || '服务器返回错误'));
                }
              } catch (e) {
                console.error('❌ [富文本编辑器] 解析响应失败:', e);
                console.error('❌ [富文本编辑器] 原始响应数据:', uploadRes.data);
                reject(new Error('解析服务器响应失败'));
              }
            } else {
              console.error('❌ [富文本编辑器] HTTP状态码错误:', uploadRes.statusCode);
              reject(new Error(`上传失败，HTTP ${uploadRes.statusCode}`));
            }
          },
          fail: (err) => {
            console.error('❌ [富文本编辑器] 上传请求失败:', err);
            console.error('❌ [富文本编辑器] 错误详情:', JSON.stringify(err));

            // 判断具体错误类型
            if (err.errMsg) {
              if (err.errMsg.includes('timeout')) {
                reject(new Error('上传超时，请检查网络'));
              } else if (err.errMsg.includes('fail')) {
                reject(new Error('网络请求失败，请重试'));
              } else {
                reject(new Error(err.errMsg));
              }
            } else {
              reject(new Error('网络请求失败'));
            }
          }
        });

        // 监听上传进度
        uploadTask.onProgressUpdate((res) => {
          const progress = res.progress || 0;
          console.log('📤 [富文本编辑器] 上传进度:', progress + '%');
          // 更新上传进度
          this.updateUploadProgress(uploadId, progress);
        });
      });
    },
    
    // 更新上传进度
    updateUploadProgress(uploadId, progress) {
      const index = this.uploadingImages.findIndex(img => img.id === uploadId);
      if (index !== -1) {
        this.uploadingImages[index].progress = Math.min(100, Math.max(0, progress));
        // 强制更新视图
        this.$forceUpdate();
      }
    },

    async convertToJpegWithMaxWidth(filePath, imageInfo) {
      const originalWidth = imageInfo.width || 0;
      const originalHeight = imageInfo.height || 0;

      if (!originalWidth || !originalHeight) {
        console.warn('⚠️ [富文本编辑器] 无法获取图片尺寸，跳过转换');
        return { path: filePath, width: originalWidth, height: originalHeight };
      }

      const targetWidth = originalWidth > 800 ? 800 : originalWidth;
      const targetHeight = Math.max(1, Math.round((originalHeight / originalWidth) * targetWidth));

      if (this.canvasWidth !== targetWidth || this.canvasHeight !== targetHeight) {
        this.canvasWidth = targetWidth;
        this.canvasHeight = targetHeight;
        await new Promise(resolve => setTimeout(resolve, 10));
      }
 
      const ctx = uni.createCanvasContext('featureEditorTempCanvas', this);
      ctx.clearRect(0, 0, targetWidth, targetHeight);
      ctx.drawImage(filePath, 0, 0, originalWidth, originalHeight, 0, 0, targetWidth, targetHeight);

      await new Promise(resolve => ctx.draw(false, resolve));

      const jpegPath = await new Promise((resolve, reject) => {
        uni.canvasToTempFilePath({
          canvasId: 'featureEditorTempCanvas',
          width: targetWidth,
          height: targetHeight,
          destWidth: targetWidth,
          destHeight: targetHeight,
          fileType: 'jpg',
          quality: 0.9,
          success: res => resolve(res.tempFilePath),
          fail: reject
        }, this);
      });

      return { path: jpegPath, width: targetWidth, height: targetHeight };
    },

    async applyNormalizedImageStyles() {
      if (!this.editorCtx) return;

      try {
        const selection = await new Promise(resolve => {
          this.editorCtx.getSelection({
            success: res => resolve(res),
            fail: () => resolve(null)
          });
        });

        const currentHtml = await this.getEditorContent();
        const normalizedHtml = this.normalizeEditorHtml(currentHtml);

        if (normalizedHtml !== currentHtml) {
          await new Promise((resolve, reject) => {
            this.editorCtx.setContents({
              html: normalizedHtml,
              success: () => resolve(true),
              fail: err => reject(err)
            });
          });

          if (selection && typeof selection.start === 'number' && typeof selection.end === 'number') {
            this.editorCtx.setSelection({ start: selection.start, end: selection.end });
          }
        }
      } catch (error) {
        console.warn('⚠️ [富文本编辑器] applyNormalizedImageStyles 失败:', error);
      }
    },
 
    // 获取编辑器内容
    async getEditorContent() {
      return new Promise((resolve) => {
        if (!this.editorCtx) {
          resolve('');
          return;
        }
        this.editorCtx.getContents({
          success: (res) => {
            resolve(res.html || '');
          }
        });
      });
    },

    normalizeEditorHtml(html) {
      if (!html) {
        return html;
      }

      return html.replace(/<img[^>]*>/gi, (imgTag) => {
        let cleanedTag = imgTag;

        cleanedTag = cleanedTag.replace(/\s+(width|height)\s*=\s*"[^"]*"/gi, '');
        cleanedTag = cleanedTag.replace(/\s+(width|height)\s*=\s*'[^']*'/gi, '');

        cleanedTag = cleanedTag.replace(/\s+style\s*=\s*"([^"]*)"/gi, (match, styleValue) => {
          const normalizedStyles = styleValue
            .split(';')
            .map(style => style.trim())
            .filter(style => style && !/^width\s*:/i.test(style) && !/^height\s*:/i.test(style) && !/^max-width\s*:/i.test(style) && !/^aspect-ratio\s*:/i.test(style));

          normalizedStyles.push('width:100% !important');
          normalizedStyles.push('max-width:100% !important');
          normalizedStyles.push('height:auto !important');
          normalizedStyles.push('display:block');

          const srcMatch = cleanedTag.match(/src=["']([^"']+)["']/i);
          const src = srcMatch ? srcMatch[1] : '';
          const cached = this.imageDimensionCache[src];
          if (cached && cached.width > 0 && cached.height > 0) {
            normalizedStyles.push(`aspect-ratio: ${cached.width} / ${cached.height}`);
            if (!/data-aspect=/i.test(cleanedTag)) {
              cleanedTag = cleanedTag.replace(/<img/i, `<img data-aspect="${cached.width}:${cached.height}"`);
            }
          }

          const dedupedStyles = Array.from(new Set(normalizedStyles));

          return dedupedStyles.length ? ` style="${dedupedStyles.join('; ')}"` : '';
        });

        if (!/\sstyle=/i.test(cleanedTag)) {
          const srcMatch = cleanedTag.match(/src=["']([^"']+)["']/i);
          const src = srcMatch ? srcMatch[1] : '';
          const cached = this.imageDimensionCache[src];
          const baseStyles = ['width:100% !important', 'max-width:100% !important', 'height:auto !important', 'display:block'];
          if (cached && cached.width > 0 && cached.height > 0) {
            baseStyles.push(`aspect-ratio: ${cached.width} / ${cached.height}`);
            if (!/data-aspect=/i.test(cleanedTag)) {
              cleanedTag = cleanedTag.replace(/<img/i, `<img data-aspect="${cached.width}:${cached.height}"`);
            }
          }
          cleanedTag = cleanedTag.replace(/<img/i, `<img style="${baseStyles.join('; ')}"`);
        }

        return cleanedTag;
      });
    },

    // 提取HTML中的图片URL
    extractImagesFromHtml(html) {
      const images = [];
      const imgRegex = /<img[^>]+src=["']([^"']+)["'][^>]*>/gi;
      let match;

      while ((match = imgRegex.exec(html)) !== null) {
        images.push({
          type: 'image',
          imgUrl: match[1],
          alt: '产品特色图片',
          order: images.length
        });
      }

      return images;
    },
    
    // 按照HTML中的顺序提取文本和图片
    extractFeaturesFromHtml(html) {
      const features = [];
      let order = 0;
      
      if (!html || !html.trim()) {
        return features;
      }
      
      // 使用正则表达式匹配HTML中的段落标签
      const pRegex = /<p[^>]*>(.*?)<\/p>/gi;
      const matches = [];
      
      // 匹配所有段落
      let pMatch;
      while ((pMatch = pRegex.exec(html)) !== null) {
        const content = pMatch[1];
        const imgMatch = content.match(/<img[^>]+src=["']([^"']+)["'][^>]*>/i);
        
        if (imgMatch) {
          // 段落中包含图片
          const imgIndex = content.indexOf(imgMatch[0]);
          
          // 提取图片前的文本
          const textBefore = content.substring(0, imgIndex)
            .replace(/<[^>]*>/g, '')
            .replace(/&nbsp;/g, ' ')
            .trim();
          
          // 提取图片后的文本
          const textAfter = content.substring(imgIndex + imgMatch[0].length)
            .replace(/<[^>]*>/g, '')
            .replace(/&nbsp;/g, ' ')
            .trim();
          
          // 按照顺序添加：文本前 -> 图片 -> 文本后
          if (textBefore) {
            matches.push({
              index: pMatch.index,
              type: 'text',
              alt: textBefore,
              order: order++
            });
          }
          
          matches.push({
            index: pMatch.index + imgIndex,
            type: 'image',
            imgUrl: imgMatch[1],
            order: order++
          });
          
          if (textAfter) {
            matches.push({
              index: pMatch.index + imgIndex + imgMatch[0].length,
              type: 'text',
              alt: textAfter,
              order: order++
            });
          }
        } else {
          // 段落中只有文本
          const textContent = content
            .replace(/<[^>]*>/g, '')
            .replace(/&nbsp;/g, ' ')
            .trim();
          
          if (textContent) {
            matches.push({
              index: pMatch.index,
              type: 'text',
              alt: textContent,
              order: order++
            });
          }
        }
      }
      
      // 按位置排序（确保顺序正确）
      matches.sort((a, b) => {
        if (a.index !== b.index) {
          return a.index - b.index;
        }
        return a.order - b.order;
      });
      
      // 重新分配order，确保顺序正确
      matches.forEach((match, index) => {
        match.order = index;
      });
      
      // 转换为features格式
      matches.forEach(match => {
        if (match.type === 'image') {
          features.push({
            type: 'image',
            imgUrl: match.imgUrl,
            alt: '产品特色图片',
            order: match.order
          });
        } else if (match.type === 'text') {
          features.push({
            type: 'text',
            alt: match.alt,
            imgUrl: '',
            order: match.order
          });
        }
      });
      
      return features;
    },

    // 保存特色数据
    async saveFeatures() {
      if (this.isSaving) return;
      
      // 检查是否有正在上传的图片
      if (this.hasUploadingImages) {
        uni.showToast({
          title: '图片正在上传中，请稍候...',
          icon: 'none',
          duration: 2000
        });
        return;
      }
      
      // 检查HTML中是否有本地临时路径
      const editorContent = await this.getEditorContent();
      if (this.hasLocalImagePaths(editorContent)) {
        uni.showModal({
          title: '提示',
          content: '检测到有图片未上传完成，是否继续保存？',
          confirmText: '继续保存',
          cancelText: '取消',
          success: (res) => {
            if (res.confirm) {
              this.doSave();
            }
          }
        });
        return;
      }
      
      this.doSave();
    },
    
    // 执行保存操作
    async doSave() {
      if (this.isSaving) return;

      this.isSaving = true;

      try {
        // 获取编辑器中的HTML内容
        const editorContent = await this.getEditorContent();
        const normalizedContent = this.normalizeEditorHtml(editorContent);

        console.log('=== 开始保存产品特色 ===');
        console.log('编辑器原始HTML内容:', editorContent);
        console.log('编辑器内容长度:', editorContent.length);

        // 更新store中的数据
        if (!this.productStore.subPageData) {
          this.productStore.subPageData = {
            productFeatures: [],
            productFeaturesHtml: '',
            productFeaturesCustom: [],
            productFeaturesCustomHtml: '',
            specificItinerary: [],
            expensesIncluded: [],
            expensesExcluded: [],
            otherExpenses: [],
            riskPrompt: '',
            guaranteePrompt: ''
          };
          console.log('初始化 subPageData');
        }

        const dataKey = this.isCustom ? 'productFeaturesCustom' : 'productFeatures';
        const htmlKey = this.isCustom ? 'productFeaturesCustomHtml' : 'productFeaturesHtml';

        // 如果编辑器有内容，直接保存HTML
        if (normalizedContent.trim() && normalizedContent !== '<p><br></p>' && normalizedContent !== '<p></p>') {
          // 直接保存HTML内容用于富文本显示
          this.productStore.subPageData[htmlKey] = normalizedContent;
          console.log(`✅ 已保存HTML内容到 ${htmlKey}`);

          // 按照HTML中的实际顺序提取文本和图片
          const productFeatures = this.extractFeaturesFromHtml(normalizedContent);

          console.log(`按顺序提取的${dataKey}:`, productFeatures);
          console.log(`${dataKey}数量:`, productFeatures.length);

          this.productStore.subPageData[dataKey] = productFeatures;
          console.log(`✅ 已保存结构化数据到 ${dataKey}（用于API）`);
          console.log(`${dataKey}:`, JSON.stringify(productFeatures, null, 2));
        } else {
          // 如果编辑器为空，清空所有内容
          this.productStore.subPageData[htmlKey] = '';
          this.productStore.subPageData[dataKey] = [];
          console.log(`⚠️ 编辑器为空，清空所有${this.isCustom ? '产品特色自定义' : '产品特色'}数据`);
        }

        console.log('=== 保存完成 ===');

        uni.showToast({
          title: '保存成功',
          icon: 'success',
          duration: 1500
        });

        // 延迟返回，让用户看到成功提示
        setTimeout(() => {
          console.log('准备返回上一页');
          console.log('HTML内容:', this.productStore.subPageData.productFeaturesHtml);
          console.log('结构化数据:', JSON.stringify(this.productStore.subPageData.productFeatures, null, 2));
          uni.navigateBack();
        }, 1500);
      } catch (error) {
        console.error('❌ 保存失败:', error);
        uni.showToast({ title: '保存失败，请重试', icon: 'none' });
      } finally {
        this.isSaving = false;
      }
    },

    // 返回
    goBack() {
      uni.navigateBack();
    },

    // 应用图片样式规范化
    applyNormalizedImageStyles() {
      if (!this.editorCtx) {
        return;
      }
      this.editorCtx.format('image', {
        style: 'width:100% !important; max-width:100% !important; height:auto !important; display:block'
      });
    }
  }
};
</script>

<style lang="scss" scoped>
.editor-container {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  background: #f5f7fa;
}

/* 工具栏 */
.toolbar {
  position: fixed;
  top: 140rpx;
  left: 0;
  right: 0;
  min-height: 100rpx;
  background: #ffffff;
  border-bottom: 1rpx solid #ebeef5;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  padding: 16rpx 20rpx 20rpx 20rpx;
  gap: 16rpx;
  z-index: 98;
  box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.05);
  box-sizing: border-box;
  overflow: hidden;
}

.toolbar-group {
  display: flex;
  gap: 12rpx;
  align-items: center;
  padding: 0 12rpx;
  border-right: 1rpx solid #ebeef5;

  &:last-child {
    border-right: none;
  }
}

.toolbar-btn {
  width: 56rpx;
  height: 56rpx;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #f5f7fa;
  border-radius: 8rpx;
  transition: all 0.3s ease;

  &:active {
    background: #e0e0e0;
    transform: scale(0.95);
  }

  &.active {
    background: #5677fc;

    .btn-icon,
    .btn-text {
      color: #ffffff;
    }
  }
}

.btn-icon,
.btn-text {
  font-size: 28rpx;
  font-weight: 600;
  color: #5677fc;
  transition: color 0.3s ease;
}

/* 编辑器区域 */
.editor-wrapper {
  position: fixed;
  top: 280rpx;
  left: 0;
  right: 0;
  bottom: 160rpx;
  padding: 0 24rpx 24rpx 24rpx;
  overflow: auto;
  box-sizing: border-box;
  z-index: 97;
}

.ql-container {
  width: 100%;
  height: 100%;
  background: #ffffff;
  border: 1rpx solid #ebeef5;
  border-radius: 12rpx;
  padding: 20rpx;
  font-size: 28rpx;
  line-height: 1.8;
  box-sizing: border-box;
}

/* 底部按钮 */
.bottom-bar {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  padding: 20rpx 24rpx;
  background: #ffffff;
  border-top: 1rpx solid #ebeef5;
  box-shadow: 0 -2rpx 12rpx rgba(0, 0, 0, 0.05);
  display: flex;
  gap: 16rpx;
}

.btn-cancel,
.btn-save {
  flex: 1;
  height: 88rpx;
  font-size: 28rpx;
  font-weight: 500;
  border-radius: 12rpx;
  border: none;
  transition: all 0.3s ease;
  line-height: 88rpx;
}

.btn-cancel {
  background: #f5f7fa;
  color: #606266;
}

.btn-save {
  background: linear-gradient(135deg, #5677fc 0%, #7b8cff 100%);
  color: #ffffff;
  box-shadow: 0 4rpx 16rpx rgba(86, 119, 252, 0.3);

  &:active {
    transform: translateY(2rpx);
    box-shadow: 0 2rpx 8rpx rgba(86, 119, 252, 0.4);
  }

  &[disabled] {
    opacity: 0.6;
  }
}

.btn-cancel:active {
  transform: scale(0.98);
}

/* 上传进度容器 */
.upload-progress-container {
  position: fixed;
  bottom: 160rpx;
  left: 24rpx;
  right: 24rpx;
  z-index: 999;
  background: #ffffff;
  border-radius: 12rpx;
  box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.15);
  padding: 24rpx;
  max-height: 400rpx;
  overflow-y: auto;
}

.upload-progress-item {
  margin-bottom: 24rpx;
  
  &:last-child {
    margin-bottom: 0;
  }
}

.upload-progress-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 16rpx;
}

.upload-progress-text {
  font-size: 26rpx;
  color: #333333;
  font-weight: 500;
}

.upload-progress-percent {
  font-size: 24rpx;
  color: #5677fc;
  font-weight: 600;
}

.upload-progress-bar {
  width: 100%;
  height: 8rpx;
  background: #f0f0f0;
  border-radius: 4rpx;
  overflow: hidden;
  margin-bottom: 12rpx;
}

.upload-progress-fill {
  height: 100%;
  background: linear-gradient(90deg, #5677fc 0%, #7b8cff 100%);
  border-radius: 4rpx;
  transition: width 0.3s ease;
  position: relative;
  
  &::after {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: linear-gradient(
      90deg,
      transparent 0%,
      rgba(255, 255, 255, 0.3) 50%,
      transparent 100%
    );
    animation: shimmer 1.5s infinite;
  }
}

@keyframes shimmer {
  0% {
    transform: translateX(-100%);
  }
  100% {
    transform: translateX(100%);
  }
}

.upload-progress-status {
  display: flex;
  align-items: center;
  justify-content: center;
  margin-top: 8rpx;
}

.upload-status-text {
  font-size: 22rpx;
  
  &.success {
    color: #52c41a;
  }
  
  &.failed {
    color: #ff4d4f;
  }
}
</style>
